package com.wfm.files;

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class MultiThreadedFileProcessorOptimized {
    private static final int THREAD_COUNT = 5;
    private static final int LINES_PER_THREAD = 1000;

    public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
        String fileAPath = "input.txt"; // 输入文件
        String fileBPath = "output.txt"; // 输出文件

        // 1. 计算每行的起始位置和长度
        List<LineInfo> lineInfos = calculateLineInfos(fileAPath);

        // 2. 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);

        // 3. 分配任务给线程
        int totalLines = lineInfos.size();
        for (int i = 0; i < totalLines; i += LINES_PER_THREAD) {
            final int start = i;
            final int end = Math.min(i + LINES_PER_THREAD, totalLines);
            executor.submit(() -> {
                try {
                    transferLines(fileAPath, fileBPath, lineInfos.subList(start, end));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }

        // 4. 关闭线程池
        executor.shutdown();
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    }

    private static List<LineInfo> calculateLineInfos(String filePath) throws IOException {
        List<LineInfo> lineInfos = new ArrayList<>();
        long position = 0;

        try (RandomAccessFile file = new RandomAccessFile(filePath, "r")) {
            while (file.getFilePointer() < file.length()) {
                String line = file.readLine();
                if (line != null) {
                    // +2是因为有回车+换行
                    lineInfos.add(new LineInfo(position, line.length() + 2)); // +1 for newline
                    position += line.length() + 2;
                }
            }
        }

        return lineInfos;
    }

    private static void transferLines(String fileAPath, String fileBPath, List<LineInfo> lines) throws IOException {
        try (FileChannel sourceChannel = FileChannel.open(Paths.get(fileAPath), StandardOpenOption.READ);
             FileChannel destChannel = FileChannel.open(Paths.get(fileBPath), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {

            for (LineInfo lineInfo : lines) {
                long position = lineInfo.position;
                int length = lineInfo.length;

                // 从 sourceChannel 读取指定区域
                MappedByteBuffer sourceBuffer = sourceChannel.map(FileChannel.MapMode.READ_ONLY, position, length);
                System.out.println("Reading line from position: " + position + ", length: " + length+"  ");
                // 把sourceBuffer变成字节数组
                destChannel.write(sourceBuffer);
            }
        }
    }

    static class LineInfo {
        long position; // 行的起始位置
        int length;    // 行的长度（包括换行符）

        LineInfo(long position, int length) {
            this.position = position;
            this.length = length;
        }
    }
}